﻿using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.Phone.Tasks;
using TheVerge.Base;
using TheVerge.Phone.Converters;
using TheVerge.Phone.Imp;
using Microsoft.Phone.Controls;
using TheVerge.Base.Models;
using Microsoft.Phone.Shell;
using System.Collections.Generic;
using System.Windows.Media.Animation;

namespace TheVerge.Phone.Controls {
	/// <summary>
	/// Special thanks to the following for help with launching all links in
	/// a web browser task instead of the existing WebBrowserControl.
	/// See: http://4mkmobile.com/2010/10/quick-tip-changing-all-links-to-open-using-the-webbrowsertask/
	/// </summary>
	public partial class ArticleEntryControl : UserControl {
        //-- Original Font Size
        // Body: 128%
        // Title: 176%
        // Diff: 1.375
        #region HTML
        /// <summary>
        /// http://social.msdn.microsoft.com/forums/en-us/wpdevelop/thread/3c5107dc-f286-4d5d-98dd-0c688bd4f5e0
        /// Special thanks to that forum post to help see the value of including the doctype in the web browser control.
        /// </summary>
        private const string HTML = @"
<?xml version=""1.0"" encoding=""UTF-8""?>
<!DOCTYPE html PUBLIC ""-//WAPFORUM//DTD XHTML Mobile 1.2//EN"" ""http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd"">
<html>
	<head>
		<meta name=""viewport"" content=""width=480"" />
		<style type=""text/css"">
			body {{
				background-color:{0};
				color:{1};
				font-size:{5}%;
                font-weight:lighter;
			}}
			a {{ color:{2}; }}

			.Title {{
				font-size:{5}%;
                font-weight:bold;
				color:{2};
			}}

			.Subtle {{
				color:{3};
			}}

			.SourceName {{
				background-color:{2};
				border:2px solid {0};
				color:{0};
				padding:3px 5px;
				float: left;
			}}

			.SourceLinkDiv {{
				background-color:{3};
				border:2px solid {0};
				padding:3px 5px;
				float: left;
			}}

			.SourceLink {{ 
				text-decoration:none;
				color:{0};
			}}

		</style>
	</head>

	<body>{4}</body>
	<script>
			window.onload = function() {{
				a = document.getElementsByTagName('a');
				for(var i=0; i < a.length; i++) {{
					a[i].attachEvent('onclick', notify);
					
				}}
			}}

			function notify(evt) {{
				window.external.Notify(evt.srcElement.href); 

				if (evt) {{
					evt.returnValue = false;
				}} 
				
				return false;
			}}
		</script>	
</html>";
        #endregion

        private ArticleEntry ActiveArticle;
        private CompositeTransform moveTransform;
        
        private FromNowDateTimeConverter Conv = new FromNowDateTimeConverter();
        private Storyboard showSB;
        private Storyboard hideSB;
        private Duration sbDuration = new Duration(TimeSpan.FromSeconds(0.5D));

        public bool IsOverlayVisible { get { return sharePane.IsVisible(); } }
        public bool IsVisible { get; private set; }

		public event EventHandler ArticleLoaded = delegate { };

		public ArticleEntryControl() {
			InitializeComponent();
            AppBarHelper.ShareAction = ToggleShare;

            this.RenderTransform = moveTransform = new CompositeTransform();

            //-- By Default it's hidden
            Opacity = 0D; 
            moveTransform.TranslateY = ActualHeight;
		}

        public void InitArticleViewer(double width, double height)
        {
            Width = width;
            Height = height;

            //-- Hide
            CreateStoryBoard(ref hideSB, height, 0D);

            //-- Show
            CreateStoryBoard(ref showSB, 0D, 1D);

            if(!IsVisible)
                moveTransform.TranslateY = height;
        }

        private void CreateStoryBoard(ref Storyboard sb, double y, double Opacity)
        {
            var translateY = new DoubleAnimation() { To = y };
            var opacity = new DoubleAnimation() { To = Opacity };
            translateY.Duration = opacity.Duration = sbDuration;
            sb = new Storyboard();
            sb.Children.Add(translateY);
            sb.Children.Add(opacity);
            Storyboard.SetTarget(translateY, moveTransform);
            Storyboard.SetTarget(opacity, this);
            Storyboard.SetTargetProperty(translateY, new PropertyPath(CompositeTransform.TranslateYProperty));
            Storyboard.SetTargetProperty(opacity, new PropertyPath(FrameworkElement.OpacityProperty));
        }

        private IEnumerable<IApplicationBarIconButton> Buttons
        {
            get
            {
                yield return AppBarHelper.IEButton;
                yield return AppBarHelper.ShareButton;
                yield return AppBarHelper.CommentsButton;
            }
        }

        private IEnumerable<IApplicationBarMenuItem> Items
        {
            get { yield return AppBarHelper.SettingsItem; }
        }

        public void HideOverlay()
        {
            if (sharePane.IsVisible())
                sharePane.Hide();
        }

        public void Hide()
        {
            AppBarHelper.LoadFromPage();
            IsVisible = false;
            hideSB.Begin();
        }

		public void LoadEntry(ArticleEntry e) {
            ActiveArticle = App.MainVM.ActiveArticle = e;
            AppBarHelper.Load(Buttons, Items, false);
            
            HideOverlay();
            theBrowser.NavigateToString(CreateHtml(e));
            commentsControl.Load(e);
            IsVisible = true;

            DataContext = e;
            showSB.Begin();
		}

        public void Refresh()
        {
            if (ActiveArticle != null)
                LoadEntry(ActiveArticle);
        }

        private string CreateHtml(ArticleEntry e) {
			var sb = new StringBuilder();
			sb.AppendFormat("<p class='Title'>{0}</p>", e.Title);
			sb.AppendFormat("<p>By <bold>{0}</bold> <span class='Subtle'>{1}</span></p>", e.AuthorName, Conv.Convert(e.PublishedOn, null, null, null));
			sb.Append(e.Body);
			sb.Append(GetSourceList("VIA", e.ViaList));
			sb.Append(GetSourceList("SOURCE", e.SourceList));
            sb.Append(@"<br />");
            sb.Append(@"<br />");

            return string.Format(HTML, GetHex(BackColor), GetHex(ForegroundColor), GetHex(AccentColor), GetHex(SubtleColor), sb, Theme.Active.FontSize);
		}

		private static string GetSourceList(string sourceName, Source[] list) {
			if (null == list || list.Length == 0) return string.Empty;
			StringBuilder sb = new StringBuilder();
			sb.AppendFormat(@"<div class='SourceName'>{0}</div>", sourceName);
			foreach (var s in list) {
				sb.AppendFormat(@"<div class='SourceLinkDiv'><a class='SourceLink' href='{0}'>{1}</a></div>", s.Url, s.Name.ToUpper());
			}
			sb.Append("<div style='clear:both;height:1px;' />");
			return sb.ToString();
		}

        private Color AccentColor { get { return ThemeManager.Accent; } }
        private Color BackColor { get { return ThemeManager.Background; } }
        private Color ForegroundColor { get { return ThemeManager.Foreground; } }
        private Color SubtleColor { get { return ThemeManager.Subtle; } }

		private static string GetHex(Color c) {
			return string.Format("#{0:X2}{1:X2}{2:X2}", c.R, c.G, c.B);
		}

		private void theBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e) {
			ArticleLoaded(this, EventArgs.Empty);
		}

		private void theBrowser_NavigationFailed(object sender, System.Windows.Navigation.NavigationFailedEventArgs e) {
            ArticleLoaded(this, EventArgs.Empty);
            MessageBox.Show("There was an error loading the page.");
		}

		private void theBrowser_ScriptNotify(object sender, Microsoft.Phone.Controls.NotifyEventArgs e) {
            try
            {
                var wbt = new WebBrowserTask();
                wbt.Uri = new Uri(e.Value, UriKind.Absolute);
                wbt.Show();
            } //-- Sometimes we may get an invalid Uri, as a result, we need to catch this exception.
            catch (Exception) {
                MessageBox.Show("Unable to launch link. This could be do to a poorly formatted Uri or an invalid protocol.");
            }
        }

        #region Sharing
        #region Event Handlers
        private void Copy_Click(object sender, RoutedEventArgs e) { ArticleExecutor(Copy); }

        private void Email_Click(object sender, RoutedEventArgs e) { ArticleExecutor(Email); }

        private void SMS_Click(object sender, RoutedEventArgs e) { ArticleExecutor(SMS); }

        private void Social_Click(object sender, RoutedEventArgs e) { ArticleExecutor(Social); }
        #endregion

        private void ArticleExecutor(Action<ArticleEntry> action)
        {
            sharePane.Hide(); 
            
            var article = App.MainVM.ActiveArticle;
            if (article != null)
                action(article);
        }

        private void ToggleShare()
        {
            if (sharePane.IsVisible())
                sharePane.Hide();
            else
                sharePane.Show();
        }

        private void Copy(ArticleEntry article)
        {
            if (article == null) return;
            Clipboard.SetText(article.Url);
            MessageBox.Show(string.Format("'{0}' has been copied to your clipboard.", article.Url), "Link Copied", MessageBoxButton.OK);
        }

        private void Email(ArticleEntry article)
        {
            if (article == null) return;
            var t = new EmailComposeTask();
            t.Subject = article.Title;
            t.Body = string.Format("'{0}'\n\n via The Verge Windows Phone App", article.Url);
            t.Show();
        }

        private void SMS(ArticleEntry article)
        {
            if (article == null) return;
            var sms = new SmsComposeTask();
            sms.Body = string.Format("'{0}'\n\n{1}", article.Title, article.Url);
            sms.Show();
        }

        private void Social(ArticleEntry article)
        {
            if (article == null) return;

            var share = new ShareLinkTask();
            share.LinkUri = new Uri(article.Url);
            share.Title = article.Title;
            share.Show();
        }
        #endregion
    }
}
